package com.wchat.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.wchat.bean.enums.FileTypeEm;
import com.wchat.service.MediaTransferService;
import com.wchat.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.mockito.internal.util.collections.Sets;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

/**
 * @author : willian fu
 * @date : 2021/8/31
 */
@Slf4j
@Service
public class MediaTransferServiceImpl implements MediaTransferService {

    private static final String BASE_PATH = System.getProperty("user.dir");

    private static final Set<String> soundType = Sets.newSet("aac", "mp3", "wav", "pcm");
    private static final Set<String> imageType = Sets.newSet("jpg", "bmp", "gif", "png", "tif", "jpeg");
    private static final Set<String> videoType = Sets.newSet("flv", "mp4", "mov", "avi", "mkv", "wmv", "m4v", "3gp", "rmvb");

    @Override
    public Object uploadAvatar(MultipartFile file) {
        if (file.getSize() > 1024 * 500){
            return R.badRequest("头像不能大于500KB");
        }
        return uploadImage(file);
    }

    @Override
    public void getImage(HttpServletResponse rsp, Boolean isAvatar, String fileName) {
        getSource(fileName, rsp);
    }

    @Override
    public void getResource(HttpServletResponse rsp, String fileName) {
        getSource(fileName, rsp);
    }

    @Override
    public Object uploadFile(MultipartFile file) {
        String fileType = getFileType(file.getOriginalFilename());
        String path = "";
        Map<String, String> fileInfo = new HashMap<>();
        fileInfo.put("original", file.getOriginalFilename());
        if (imageType.contains(fileType)) {
            path = saveSource(FileTypeEm.IMAGE.getPath(), file);
        } else if (videoType.contains(fileType)) {
            path = saveSource(FileTypeEm.VIDEO.getPath(), file);
        } else if (soundType.contains(fileType)) {
            path = saveSource(FileTypeEm.SOUND.getPath(), file);
        } else {
            path = saveSource(FileTypeEm.FILE.getPath(), file);
        }
        fileInfo.put("source", path);
        if (StrUtil.isNotBlank(path)) {
            return R.ok(fileInfo);
        }
        return R.badRequest("上传失败");
    }

    @Override
    public Object uploadImage(MultipartFile file) {
        if (imageType.contains(getFileType(file.getOriginalFilename()))){
            Map<String, String> fileInfo = new HashMap<>();
            fileInfo.put("original", file.getOriginalFilename());
            String path = saveSource(FileTypeEm.IMAGE.getPath(), file);
            fileInfo.put("source", path);
            if (StrUtil.isNotBlank(path)) {
                return R.ok(fileInfo);
            }
            return R.badRequest("上传失败");
        }
       return R.badRequest("只能上传图片");
    }


    private void getSource(String fileName, HttpServletResponse response) {
        String fileType = getFileType(fileName);
        File file = null;
        InputStream inputStream = null;
        try {
            if (imageType.contains(fileType)) {
                file = new File(BASE_PATH + FileTypeEm.IMAGE.getPath() + fileName);
                if (file.exists()) {
                    inputStream = FileUtil.getInputStream(file);
                    // 设置response的Header
                    response.setContentType("image/" + fileType);
                }
            } else if (videoType.contains(fileType)) {
                file = new File(BASE_PATH + FileTypeEm.VIDEO.getPath() + fileName);
                if (file.exists()) {
                    // 设置response的Header
                    inputStream = FileUtil.getInputStream(file);
                    response.setContentType("video/" + fileType);
                    response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
                    response.setContentLength(inputStream.available());
                    response.setHeader("Content-Range", "" + (inputStream.available() - 1));
                    response.setHeader("Accept-Ranges", "bytes");
                    response.setHeader("Etag", "W/\"9767057-1323779115364\"");
                }
            } else if (soundType.contains(fileType)) {
                file = new File(BASE_PATH + FileTypeEm.SOUND.getPath() + fileName);
                if (file.exists()) {
                    // 设置response的Header
                    inputStream = FileUtil.getInputStream(file);
                    response.setContentType("multipart/form-data");
                    response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
                }
            } else {
                file = new File(BASE_PATH + FileTypeEm.FILE.getPath() + fileName);
                if (file.exists()) {
                    inputStream = FileUtil.getInputStream(file);
                    // 设置response的Header
                    response.setContentType("multipart/form-data");
                    response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
                }
            }
            if (file.exists()) {
                ServletOutputStream outputStream = response.getOutputStream();
                IoUtil.copy(inputStream, outputStream);
            } else {
                response.sendError(404, "not found source!");
            }
        } catch (IOException e) {
            log.error("请求资源[{}]异常", fileName);
        }
    }

    private String saveSource(String path, MultipartFile file) {
        try {
            String fileType = getFileType(file.getOriginalFilename());
            String md5 = SecureUtil.md5(file.getInputStream());
            String fullPath = BASE_PATH + path + md5 + "." + fileType;
            if (FileUtil.exist(fullPath)){
                return md5 + "." + fileType;
            }
            File touch = FileUtil.touch(fullPath);
            file.transferTo(touch);
            log.info("上传文件[{} => {}]成功", file.getOriginalFilename(), md5);
            return md5 + "." + fileType;
        } catch (IOException e) {
            return null;
        }
    }

    private String getFileType(String name) {
        if (StrUtil.isNotBlank(name) && name.contains(".")) {
            String[] split = name.split("\\.");
            return split[split.length - 1];
        }
        return "";
    }
}
